package com.x.client

import android.content.Context
import android.os.Environment
import android.support.multidex.MultiDexApplication
import android.text.TextUtils
import android.util.Log
import cn.jpush.android.api.JPushInterface
import com.alibaba.android.arouter.launcher.ARouter
import com.anpxd.framelibrary.net.widget.OkHttpFactory
import com.gg.utils.AppManager
import com.gg.utils.DelegatesExt
import com.gg.utils.GsonUtil
import com.gg.utils.Utils
import com.google.gson.reflect.TypeToken
import com.lsxiao.apollo.core.Apollo
import com.socks.library.KLog
import com.squareup.leakcanary.LeakCanary
import com.squareup.leakcanary.RefWatcher
import com.tencent.bugly.Bugly
import com.tencent.bugly.beta.Beta
import com.x.client.bean.User
import com.x.client.net.ApiFactory
import com.x.client.net.Response
import com.x.client.utils.AppConstant
import com.x.client.utils.VersionUtils
import io.reactivex.android.schedulers.AndroidSchedulers
import okhttp3.Interceptor
import okhttp3.ResponseBody

/**
 * Creator : GG
 * Date    : 2018/5/21
 * Mail    : gg.jin.yu@gmai.com
 * Explain :
 */
class App : MultiDexApplication() {
    companion object {
        lateinit var instance: App

        fun getRefWaktcher(context: Context): RefWatcher {
            val app: App = context.applicationContext as App
            return app.refWatcher
        }
    }


    init {
        instance = this
    }

    private lateinit var refWatcher: RefWatcher

    private var token: String by DelegatesExt.preference(this, AppConstant.TOKEN, "")

    private val beta: Boolean by lazy { packageName.contains("beta") }

    private var userInfo: String by DelegatesExt.preference(this, AppConstant.USER, "")

    private var userDetail: String by DelegatesExt.preference(this, AppConstant.USERDETAIL, "")

    override fun onCreate() {
        super.onCreate()
        refWatcher = LeakCanary.install(this)

        if (applicationInfo.packageName == Utils.getCurProcessName(applicationContext)) {
            initNet()
            Apollo.init(AndroidSchedulers.mainThread(), this, true)
            val debug = Utils.isApkInDebug(this)
            KLog.init(debug)
            if (debug) {
//                JPushInterface.setDebugMode(true)
                ARouter.openLog()
                ARouter.openDebug()
                ARouter.printStackTrace()
            }
//            JPushInterface.init(this)
//            JPushUtils.setTags(this)

//            KLog.w("registration", JPushInterface.getRegistrationID(this))
            Bugly()
            ARouter.init(this)
//            VersionUtils.checkVersion()
        }

    }


   private fun Bugly() {
        Beta.storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
        Beta.upgradeCheckPeriod = 60 * 1000
        Beta.enableNotification = false
        Beta.autoDownloadOnWifi = true
        Beta.autoCheckUpgrade = !beta
        Bugly.init(applicationContext, getString(R.string.bugly_id), beta)
    }

    private fun initNet() {
        ApiFactory.okHttpClient = OkHttpFactory.create(Interceptor {
            val originRequest = it.request()
            // 添加 header 以及公共的 GET 参数
            val newRequest = originRequest.newBuilder()
                    .addHeader("Authorization", token)
                    .addHeader("source", "android")
                    .addHeader("version", VersionUtils.getVersionName(this))
                    .url(originRequest.url().newBuilder()
//                            .addQueryParameter("uid", LocalUser.userToken?.user_id?:"unlogin")
//                            .addQueryParameter("token", LocalUser.userToken?.token?:"")
                            .build()
                    ).build()

            /** 处理不规范的返回值
             *  <-- 400 Bad Request
             *  {
             *      "code": 2,
             *      "msg": "密码错误",
             *      "result": []             // 应该返回 空对象{}, 否则 Json 解析异常
             *  }
             */
            val response = it.proceed(newRequest)
            response.newBuilder()
                    .apply {
                        KLog.w("token", response.headers().get("Authorization"))
                        KLog.w("code", response.code())
                        if (response.code() == 401) {
//                            JPushUtils.stop(this@App)
//                            JPushUtils.removeTags(this@App)
                            AppManager.finishAllActivity()
//                            startActivity(Intent(this@App, LoginActivity::class.java))
                        } else {
                            val authorization = response.headers().get("Authorization")
                            if (!authorization.isNullOrBlank())
                                token = authorization.toString()
                            val originBody = response.body()
                            var json = originBody?.string()

                            var res: Response<Any>? = null

                            try {
                                res = GsonUtil.fromJson(json.toString(), object : TypeToken<Response<Any>>() {}.type)
                            } catch (e: Exception) {
                                Log.e("initNet", "interceptor response$e")
                            }
                            try {
                                res = GsonUtil.fromJson(json.toString(), object : TypeToken<Response<List<Any>>>() {}.type)
                            } catch (e: Exception) {
                                Log.e("initNet", "interceptor response$e")
                            }

                            // 不成功，则移除 "result" 字段
                            if (1 != res?.code) {
                                res?.result = null

                            }
                            json = GsonUtil.toJson(res!!)
                            this.body(ResponseBody.create(originBody?.contentType(), json))
                        }
                    }
                    .apply {
                        KLog.w("code----", response.code())
                        this.code(if (response.code() in 400..500) 200 else response.code())
                    }
                    .build()
        })
    }


    fun getUser(): User? = if (TextUtils.isEmpty(userInfo)) null else GsonUtil.jsonToBean(userInfo, User::class.java)
            ?: User()

    fun getUserDetails(): User? = if (TextUtils.isEmpty(userDetail)) null else GsonUtil.jsonToBean(userDetail, User::class.java)
            ?: User()

    fun setUser(user: User) {
        userInfo = GsonUtil.toJson(user)
    }

    fun setUser(userInfo: String) {
        this.userInfo = userInfo
    }

    fun setUserDetails(user: User) {
        userDetail = GsonUtil.toJson(user)
    }

    fun setUserDetails(userInfo: String) {
        this.userDetail = userInfo
    }

    fun getImageUrl() = getString(R.string.image_url) ?: ""

    fun getErpUrl(): String = getString(R.string.erp_url) ?: ""


    fun getClientUrl(): String = getString(R.string.client_url) ?: ""

}
